#pragma once
#include <iostream>
#include <string>
#include <sstream>
#include <cstring>
#include <fstream>
#include <sys/stat.h>
#include <unordered_map>

#define SEP "\r\n"
#define SEPLEN strlen(SEP)
#define DEFAULT "./wwwroot"
#define HOME_PACH "index.html"
#define UNFOUND "./wwwroot/404.html"

// MIME类型映射表（常见图标及静态资源）
std::unordered_map<std::string, std::string> mimeTypes = {
    {".ico", "image/x-icon\r\n"},
    {".png", "image/png\r\n"},
    {".jpg", "image/jpeg\r\n"},
    {".jpeg", "image/jpeg\r\n"},
    {".svg", "image/svg+xml\r\n"},
    {".html", "text/html\r\n"},
    {".css", "text/css\r\n"},
    {".js", "application/javascript\r\n"}
};

//xxxxx.xxx
std::string getExtension(const std::string& path) {
    auto pos = path.rfind('.');
    std::string ret;
    if(pos != std::string::npos){
        ret = path.substr(pos);
    }
    return  ret;
}

std::string getoneline(std::string alldata){
    auto pos = alldata.find(SEP);
    std::string ret;
    if(pos != std::string::npos){
        ret = alldata.substr(0,pos);
        alldata.erase(0,pos+SEPLEN);
    }
    return ret;
}

class Request{
public:
    Request(const char* buffer) :alldata(buffer)
    {}
    void parse() {
        std::string firstline = getoneline(alldata);
        std::stringstream ss(firstline);
        ss >> methode >> url >> httpversion;
        ss >> methode >> url >> httpversion;
        
        // 构建文件路径（处理默认首页和图标）
        path += DEFAULT;
        path += url;
        
        // 处理根路径请求
        if (path[path.size() - 1] == '/') {
            path += HOME_PACH; 
        }
        
        // 记录文件扩展名
        ext = getExtension(path);
        std::cout << "File path: " << path << std::endl;  // 输出文件路径进行调试
    }
    std::string alldata;

    std::string methode;
    std::string url;
    std::string httpversion;
    std::string path;
    std::string ext;  // 文件扩展名
};

bool is_existent(const std::string& filePath){
    struct stat filesinfo;

    if(stat(filePath.c_str(),&filesinfo) == 0) return true;
    else return false;
}
off_t getfilesize(const std::string& filePath){
    struct stat filesinfo;
    if (stat(filePath.c_str(), &filesinfo) == -1) {
        std::cerr << "Failed to get file size: " << filePath << std::endl;  // 输出错误信息
        return 0;
    }
    return filesinfo.st_size;
}

//图片等信息要以二进制形式的方式读取，因此总的读取方式都是二进制读取，不能使用getline，要使用read或者istreambuf_iterator方法

void readfile(const std::string& filePath, std::string *out) {
    std::ifstream in(filePath, std::ios::binary);  // 以二进制模式打开文件
    if (!in.is_open()) {
        std::cerr << "Failed to open file: " << filePath << std::endl;  // 输出错误信息
        return;
    }
    // 读取整个文件内容
    // char buffer[getfilesize(filePath)];
    // in.read(buffer,getfilesize(filePath));
    // *out += std::string(buffer,getfilesize(filePath));
    *out += std::string((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
    in.close();
    return;
}


class Response{
public:
    std::string alldata;
    void buildResponse(const std::string& filePath, const std::string& ext) {
        std::cout<<filePath<<std::endl;

        if(is_existent(filePath)){
            alldata += "HTTP/1.1 200 OK\r\n";
            alldata += "Content-Type: ";
            alldata += mimeTypes[ext];
            //std::cout<<mimeTypes[ext]<<std::endl;
            alldata += "Content-Length: ";
            alldata += std::to_string(getfilesize(filePath));
            alldata += "\r\n";
            alldata += "\r\n";
            //构建正确响应
            readfile(filePath,&alldata);
            //std::cout<<ext<<std::endl;
        }else{
            //没有对应文件，返回404主页
            alldata += "HTTP/1.1 404 Not Found\r\n";
            alldata += "Content-Type: text/html\r\n";
            alldata += "Content-Length: ";
            alldata += std::to_string(getfilesize(UNFOUND));
            alldata += "\r\n";
            alldata += "\r\n";
            readfile(UNFOUND,&alldata);
        }
    }
};